#include "ThreadPool.h"

int Thread::generateId_ = 0;
Thread::Thread(threadFunc func)
{
    this->threadid = generateId_++;
    this->func_ = func;
}

Thread::~Thread()
{
}

int Thread::getId()
{
    return this->threadid;
}

void Thread::start()
{
    thread t(func_, threadid);
    t.detach();
}

ThreadPool::ThreadPool() : m_initThreadSize(thread::hardware_concurrency()), m_curThreadSize(0), m_idleThreadSize(0), m_maxThreadSize(MAX_THREAD_SIZE), taskMaxSize(MAX_TASK_SIZE)
{
    this->mode = PoolMode::MODE_FIXED; // 默认是固定模式
    this->is_stop = true;
    this->taskSize_ = 0;
}

ThreadPool::~ThreadPool()
{
    is_stop = true;
    notEmpty_.notify_all();
    unique_lock<mutex> lock(taskQueMux_);
    exitcondition_.wait(lock, [&]() -> bool
                        { return threads_.size() == 0; });
}

void ThreadPool::setMode(PoolMode mode)
{
    this->mode = mode;
}

void ThreadPool::setMaxThreadSize(int size)
{
    if (!is_stop)
    {
        if (this->mode == PoolMode::MODE_FIXED)
        {
            this->m_maxThreadSize = size;
        }
    }
}

void ThreadPool::setMaxTaskMaxSize(int size)
{
    if (!is_stop)
    {
        this->taskMaxSize = size;
    }
}




// void ThreadPool::submitTask(function<void()> task)
// {
//     // 提交任务以后队列不空，通知其他线程消费任务
//     unique_lock<mutex> lock(taskQueMux_);
//     // 如果满了就不能提交了
//     //  while(taskQue_.size()==this->threadMaxSize)
//     //  {
//     //      notFull_.wait(lock);
//     //  }

//     if (!notFull_.wait_for(lock, chrono::seconds(1), [&]() -> bool
//                            { return taskQue_.size() < taskMaxSize; }))
//     {
//         cout << "任务提交超时" << endl;
//         return;
//     }

//     taskQue_.emplace(task);
//     taskSize_++;
//     notEmpty_.notify_one();

//     // 动态模式
//     if (mode == PoolMode::MODE_CACHED && taskSize_ > m_idleThreadSize && m_curThreadSize < m_maxThreadSize)
//     {
//         // 创建线程
//         // 创建线程
//         auto ptr = make_unique<Thread>(bind(&ThreadPool::threadFunc, this, placeholders::_1));
//         // 放入map容器中
//         int threadid = ptr->getId();
//         threads_.emplace(make_pair(threadid, move(ptr)));
//         threads_[threadid]->start();
//         this->m_idleThreadSize++;
//         this->m_curThreadSize++;
//     }
//     return;
// }

void ThreadPool::start()
{
    this->is_stop = false;
    for (int i = 0; i < m_initThreadSize; i++)
    {
        // 创建线程
        auto ptr = make_unique<Thread>(bind(&ThreadPool::threadFunc, this, placeholders::_1));
        // 放入map容器中
        int threadid = ptr->getId();
        threads_.emplace(make_pair(threadid, move(ptr)));
    }
    for (int i = 0; i < m_initThreadSize; i++)
    {
        threads_[i]->start();
        this->m_idleThreadSize++;
        this->m_curThreadSize++;
    }
}

void ThreadPool::threadFunc(int threadid)
{
    // 这里的线程函数就是从任务队列拿取任务
    // 肯定也是循环拿取，不能拿一次就不拿了
    auto lastTime = chrono::high_resolution_clock().now();
    while (!is_stop)
    {
        function<void()> task;
        {
            unique_lock<mutex> lock(taskQueMux_);
            cout << "线程 " << this_thread::get_id() << "尝试拿取任务..." << endl;
            // 这里有两个模式的判断
            while (taskQue_.size() == 0)
            {
                if (mode == PoolMode::MODE_CACHED)
                {
                    // 动态模式说明线程可能多余了，因为任务都已经没了，所以我们就按时回收线程
                    if (cv_status::timeout == notEmpty_.wait_for(lock, chrono::seconds(1)))
                    {
                        auto now = chrono::high_resolution_clock().now();
                        auto dur = chrono::duration_cast<chrono::seconds>(now - lastTime);
                        if (dur.count() > 60 && m_curThreadSize > m_maxThreadSize)
                        {
                            threads_.erase(threadid);
                            m_curThreadSize--;
                            m_idleThreadSize--;
                            cout << "线程 " << this_thread::get_id() << "被回收" << endl;
                            return;
                        }
                    }
                }
                else
                {
                    notEmpty_.wait(lock); // 等待队列不空
                }
                // 这里可能线程池停止了，所以要进行判断一下
                if (is_stop)
                {
                    threads_.erase(threadid);
                    m_idleThreadSize--;
                    m_curThreadSize--;
                    exitcondition_.notify_one(); // 通知主线程，避免死锁
                    cout << "线程 " << this_thread::get_id() << "退出" << endl;
                    return;
                }
            }

            // 开始拿取任务
            task = taskQue_.front();
            taskQue_.pop();
            taskSize_--;

            // 如果还有任务可以继续通知
            if (taskQue_.size() > 0)
            {
                notEmpty_.notify_one();
            }
            notFull_.notify_one();
        }

        if (task)
        {
            m_idleThreadSize--;
            task();
            m_idleThreadSize++;
        }
        lastTime = chrono::high_resolution_clock().now();
    }
    // 如果到下面来，说明线程池退出了需要优雅停止,那么该线程也需要回收
    threads_.erase(threadid);
    m_curThreadSize--;
    m_idleThreadSize--;
    exitcondition_.notify_one(); // 通知主线程，避免死锁
    cout << "线程 " << this_thread::get_id() << "退出" << endl;
}
